package org.c41.graphics.effect;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.awt.image.ConvolveOp;
import java.awt.image.Kernel;

import org.c41.graphics.C41Graphic;
import org.c41.graphics.GraphicsUtil;
import org.c41.system.ImpossibleException;
import org.c41.system.Tools;

@Tools
public final class ImageEffect {

	private ImageEffect(){
		throw new ImpossibleException();
	}
	
	public static void doBlur(BufferedImage image){
		doEffect(image, EffectKernel.BLUR);
	}

	public static BufferedImage blur(BufferedImage image){
		return effect(image, EffectKernel.BLUR);
	}
	
	public static void doSharpen(BufferedImage image){
		doEffect(image, EffectKernel.SHARPEN);
	}
	
	public static BufferedImage sharpen(BufferedImage image){
		return effect(image, EffectKernel.SHARPEN);
	}
	
	public static void doCover(BufferedImage image, Color color, float alpha){
		C41Graphic g = new C41Graphic(image.createGraphics());
		g.setAlpha(alpha);
		g.fillRect(0, 0, image.getWidth(), image.getHeight());
		g.dispose();
	}
	
	public static BufferedImage cover(BufferedImage image, Color color, float alpha){
		BufferedImage bg3 = GraphicsUtil.createBufferedImage(image.getWidth(), image.getHeight());
		C41Graphic g = new C41Graphic(bg3.createGraphics());
		g.drawImage(image);
		g.setAlpha(alpha);
		g.fillRect(0, 0, image.getWidth(), image.getHeight());
		g.dispose();
		return bg3;
	}
	
	public static BufferedImage contrast(BufferedImage image, float rate){
		return effect(image, new Kernel(1, 1, new float[] { rate }));
	}
	
	public static void doContrast(BufferedImage image, float rate){
		doEffect(image, new Kernel(1, 1, new float[] { rate }));
	}
	
	private static void doEffect(BufferedImage image, Kernel kernel){
		BufferedImage bg3 = effect(image, kernel);
		Graphics g = image.createGraphics();
		g.clearRect(0, 0, image.getWidth(), image.getHeight());
		g.drawImage(bg3, 0, 0, image.getWidth(), image.getHeight(),null);
		g.dispose();
	}
	
	private static BufferedImage effect(BufferedImage image, Kernel kernel){
		BufferedImage bg3 = GraphicsUtil.createBufferedImage(image.getWidth(), image.getHeight());
		ConvolveOp op = new ConvolveOp(kernel);
		op.filter(image, bg3);
		return bg3;
	}
	
}

@Tools
final class EffectKernel{

	private EffectKernel(){
		throw new ImpossibleException();
	}
	
	public static final Kernel BLUR = new Kernel(3, 3, new float[] { 
			0.0625F, 0.125F, 0.0625F, 0.125F, 0.25F, 0.125F, 0.0625F, 0.125F, 
			0.0625F });

	public static final Kernel SHARPEN = new Kernel(3, 3, new float[] { 
			-1.0F, -1.0F, -1.0F, -1.0F, 9.0F, -1.0F, -1.0F, -1.0F, -1.0F });

}